#include "uart.hpp"
#include "commtick.hpp"
#include "dma.hpp"
#include <string.h>

using namespace device;
#define UART_IRQ_NUM		1
#define UART_MIN_TIMEOUT	20

typedef struct
{
	uint16_t tEvtSendId;
	uint16_t tEvtRecId;
	uint16_t tIrqId;
	M4_USART_TypeDef *mInstance;
}UartPartitionTPDF;

typedef struct   
{
	bool bDmaRecEnable;
	uint16_t usTimeout;
	uint16_t usLenBack;
	uint16_t usBuffLimit;
	uart *pTag;
	uint8_t *pBuff;
	uint32_t *uiDmaRecLen;
}UartCreatedTPDF;               ///> 串口创建需要的数据

static const UartPartitionTPDF mUartPartition[] =    ///> 底层串口分区
{
	{EVT_USART1_TI,	EVT_USART1_RI,	INT_USART1_RI,	M4_USART1},
	{EVT_USART2_TI,	EVT_USART2_RI,	INT_USART2_RI,	M4_USART2},
	{EVT_USART3_TI,	EVT_USART3_RI,	INT_USART3_RI,	M4_USART3},
	{EVT_USART4_TI,	EVT_USART4_RI,	INT_USART4_RI,	M4_USART4},
};

static UartCreatedTPDF mUartCreated[4] = {0};
static bool mUartTimerCreated = false;
///串口中断
extern "C"
{	
	void IRQ001_Handler(void)
	{
		if(mUartCreated[0].pTag == NULL)
		{
			return;
		}
		if(mUartCreated[0].usLenBack < mUartCreated[0].usBuffLimit)
		{
			mUartCreated[0].pBuff[mUartCreated[0].usLenBack++] = M4_USART1->DR_f.RDR;
			mUartCreated[0].usTimeout = UART_MIN_TIMEOUT;
		}
	}
	
	void IRQ002_Handler(void)
	{
		if(mUartCreated[1].pTag == NULL)
		{
			return;
		}
		if(mUartCreated[1].usLenBack < mUartCreated[1].usBuffLimit)
		{
			mUartCreated[1].pBuff[mUartCreated[1].usLenBack++] = M4_USART2->DR_f.RDR;
			mUartCreated[1].usTimeout = UART_MIN_TIMEOUT;
		}
	}
	
	void IRQ003_Handler(void)
	{
		if(mUartCreated[2].pTag == NULL)
		{
			return;
		}
		if(mUartCreated[2].usLenBack < mUartCreated[2].usBuffLimit)
		{
			mUartCreated[2].pBuff[mUartCreated[2].usLenBack++] = M4_USART3->DR_f.RDR;
			mUartCreated[2].usTimeout = UART_MIN_TIMEOUT;
		}
	}
	
	void IRQ004_Handler(void)
	{
		if(mUartCreated[3].pTag == NULL)
		{
			return;
		}
		if(mUartCreated[3].usLenBack < mUartCreated[3].usBuffLimit)
		{
			mUartCreated[3].pBuff[mUartCreated[3].usLenBack++] = M4_USART4->DR_f.RDR;
			mUartCreated[3].usTimeout = UART_MIN_TIMEOUT;
		}
	}
}

bool uart::UrtTimerCallBack(void)
{
	uint8_t i;
	for(i = 0; i < 4; i++)
	{
		if(mUartCreated[i].pTag == NULL)
		{
			continue;
		}//-Winvalid-source-encoding
		if(mUartCreated[i].bDmaRecEnable && ((mUartCreated[i].usBuffLimit - (uint16_t)((*mUartCreated[i].uiDmaRecLen) >> 16)) != mUartCreated[i].usLenBack))
		{
			mUartCreated[i].usLenBack = mUartCreated[i].usBuffLimit - ((*mUartCreated[i].uiDmaRecLen) >> 16);
			mUartCreated[i].usTimeout = UART_MIN_TIMEOUT;
		}
		if(!mUartCreated[i].usTimeout)
		{
			continue;
		}
		mUartCreated[i].usTimeout--;
		if(mUartCreated[i].usTimeout == 0)
		{
			mUartCreated[i].pTag->mRecLen = mUartCreated[i].usLenBack;
		}
	}
	return(true);
}

void uart::UartDmaSendCallBack1(void)
{
	if(mUartCreated[0].pTag == NULL)
	{
		return;
	}
	mUartCreated[0].pTag->DataSent();
}

void uart::UartDmaSendCallBack2(void)
{
	if(mUartCreated[1].pTag == NULL)
	{
		return;
	}
	mUartCreated[1].pTag->DataSent();
}

void uart::UartDmaSendCallBack3(void)
{
	if(mUartCreated[2].pTag == NULL)
	{
		return;
	}
	mUartCreated[2].pTag->DataSent();
}

void uart::UartDmaSendCallBack4(void)
{
	if(mUartCreated[3].pTag == NULL)
	{
		return;
	}
	mUartCreated[3].pTag->DataSent();
}

void uart::DataSent(void)
{
}

/** 
* @brief      构造函数
* @param[in]  tInstance  端口号
* @retval    	None
*/
uart::uart(UartInstanceTPDF tInstance, uint8_t *ucSendBuff, uint8_t *ucRecBuff, uint16_t usBuffLen)
{
	const dma::DmaCompleteDelegate mSentCallback[4] = {UartDmaSendCallBack1, UartDmaSendCallBack2, UartDmaSendCallBack3, UartDmaSendCallBack4};
	dma::DmaInitTPDF dmainit;
	
	mUartInstance = tInstance;
	mSource = 0;
	mDmaSendHandle = 0;
	mDmaRecHandle = 0;
	mRecBuff = ucRecBuff;
	mSendBuff = ucSendBuff;
	mBuffLen = usBuffLen;
	/** 超出实例个数*/
	if(((uint8_t)tInstance) > 3)
	{
		return;
	}
	/** 已被实例化*/
	if(mUartCreated[tInstance].pTag != NULL)
	{
		return;
	}
	mSemaphore = new systemos::semaphore();
	mSemaphore->Take(portMAX_DELAY);
	
	mUartCreated[tInstance].bDmaRecEnable = false;
	mUartCreated[tInstance].pBuff = mRecBuff;						///<登记实例化对象缓存
	mUartCreated[tInstance].pTag = this;								///<登记实例化对象
	mUartCreated[tInstance].usLenBack = 0;							///<实际接收长度
	mUartCreated[tInstance].usTimeout = 0;							///<超时复位
	mUartCreated[tInstance].usBuffLimit = usBuffLen;               ///>缓存限制
	mSource = mUartPartition[tInstance].mInstance;			        ///<驱动对象
	mRecLen = 0;											        ///<接收长度置0
	
//	dmainit.bCircularMode = false;
//	dmainit.tDmaCompleteCallback = mSentCallback[tInstance];
//	dmainit.tDmaDataType = dma::DMA_DATA_TYPE_UINT8;
//	dmainit.tDmaTransMode = dma::DMA_TRANS_MODE_MEM_TO_SFR;
//	dmainit.uiDest = (uint32_t)&mSource->DR;
//	dmainit.uiSrc = (uint32_t)mSendBuff;
//	dmainit.usSfrId = mUartPartition[tInstance].tEvtSendId;
//	mDmaSendHandle = dma::Request(&dmainit);
//	
//	dmainit.bCircularMode = false;
//	dmainit.tDmaCompleteCallback = 0;
//	dmainit.tDmaDataType = dma::DMA_DATA_TYPE_UINT8;
//	dmainit.tDmaTransMode = dma::DMA_TRANS_MODE_SFR_TO_MEM;
//	dmainit.uiDest = (uint32_t)mRecBuff;
//	dmainit.uiSrc = ((uint32_t)&mSource->DR) + 2;
//	dmainit.usSfrId = mUartPartition[tInstance].tEvtRecId;
//	mDmaRecHandle = dma::Request(&dmainit);
	/** 串口中断使能*/
	if(!mDmaRecHandle)
	{
		*(uint32_t *)(((uint32_t)&M4_INTC->SEL0) + (4 * (UART_IRQ_NUM + tInstance))) = mUartPartition[tInstance].tIrqId;
		NVIC_ClearPendingIRQ((IRQn)(UART_IRQ_NUM + tInstance));
		NVIC_SetPriority((IRQn)(UART_IRQ_NUM + tInstance), 4);
		NVIC_EnableIRQ((IRQn)(UART_IRQ_NUM + tInstance));
	}
	else
	{
		dma::StartDma(mDmaRecHandle, usBuffLen);
		mUartCreated[mUartInstance].uiDmaRecLen = dma::GetLengthRegister(mDmaRecHandle);
		mUartCreated[mUartInstance].bDmaRecEnable = true;
	}
	if(!mUartTimerCreated)
	{
		commtick::RegisteTick(UrtTimerCallBack,1);
		mUartTimerCreated = true;
	}
	mSemaphore->Give();
}

/**
* @brief      析构函数
* @retval    	None
*/
uart::~uart(void)
{
	uart::Close();
	mUartCreated[mUartInstance].pTag = 0;						///<注销实例化对象
}

bool uart::Open(void)
{
	uint32_t pclk;
	
	/** 无驱动对象*/
	if(mSource == NULL)
	{
		return(false);
	}
	mSemaphore->Take(portMAX_DELAY);
	/** 默认波特率*/
	if(BaudRate == 0)
	{
		BaudRate = 9600;
	}
	/** 开启驱动*/
	pclk = ClockFreqGet(CLOCK_TYPE_APB1);
	mSource->CR1 = 0x801B0000;
	mSource->CR2 = 0x00000000;
	mSource->CR3 = 0x00000000;
	if(pclk > (BaudRate * 8 * 256 * 64))
	{
		mSemaphore->Give();
		return(false);
	}
	if(!mDmaRecHandle)
	{
		*(uint32_t *)(((uint32_t)&M4_INTC->SEL0) + (4 * (UART_IRQ_NUM + mUartInstance))) = mUartPartition[mUartInstance].tIrqId;
		NVIC_ClearPendingIRQ((IRQn)(UART_IRQ_NUM + mUartInstance));
		NVIC_SetPriority((IRQn)(UART_IRQ_NUM + mUartInstance), 4);
		NVIC_EnableIRQ((IRQn)(UART_IRQ_NUM + mUartInstance));
	}
	else
	{
		dma::StartDma(mDmaRecHandle, mBuffLen);
		mUartCreated[mUartInstance].uiDmaRecLen = dma::GetLengthRegister(mDmaRecHandle);
		mUartCreated[mUartInstance].bDmaRecEnable = true;
	}
	if(pclk > (BaudRate * 8 * 256 * 16))
	{
		mSource->PR = 3;
		pclk >>= 6;
	}
	else if(pclk > (BaudRate * 8 * 256 * 4))
	{
		mSource->PR = 2;
		pclk >>= 4;
	}
	else if(pclk > (BaudRate * 8 * 256))
	{
		mSource->PR = 1;
		pclk >>= 2;
	}
	else
	{
		mSource->PR = 0;
	}
	mSource->BRR_f.DIV_INTEGER = (pclk / (8 * BaudRate)) - 1;
	mSource->BRR_f.DIV_FRACTION = (pclk / (800 * (mSource->BRR_f.DIV_INTEGER + 1) * BaudRate)) - 1;
	switch(Parity)
	{
			case UART_PARITY_TYPE_NONE:
					mSource->CR1_f.PCE = 0;
					break;
			case UART_PARITY_TYPE_EVEN:
					mSource->CR1_f.PS = 0;
					mSource->CR1_f.PCE = 1;
					break;
			case UART_PARITY_TYPE_ODD:
					mSource->CR1_f.PS = 1;
					mSource->CR1_f.PCE = 1;
					break;
			default:
					break;
	}
	mSource->CR1_f.OVER8 = 1;
	if(!mDmaRecHandle)
	{
		mSource->CR1_f.RIE = 1;
	}
	else
	{
		mSource->CR1_f.RIE = 0;
	}
	mSource->CR1_f.TE = 1;
	mSource->CR1_f.RE = 1;
	
	mSemaphore->Give();
	return(true);
}

void uart::Close(void)
{
	if(mSource == NULL)
	{
		return;
	}
	/** 中断禁止*/
	mUartCreated[mUartInstance].bDmaRecEnable = false;
	mSource->CR1 = 0;
}

bool uart::Write(uint8_t *ucData, uint16_t usDataLen)
{
	uint16_t i;
	/** 无驱动对象*/
	if(mSource == NULL)
	{
		return(false);
	}
	mSemaphore->Take(portMAX_DELAY);
	if(mDmaSendHandle)
	{
		dma::StartDma(mDmaSendHandle, usDataLen, usDataLen, 0, ucData);
		mSource->CR1_f.TE = 0;
		mSource->CR1_f.TE = 1;
		mSemaphore->Give();
		return(true);
	}
	for(i = 0; i < usDataLen; i++)
	{
		while(!mSource->SR_f.TXE);
		mSource->DR_f.TDR = ucData[i];
		while(!mSource->SR_f.TC);
	}
	DataSent();
	mSemaphore->Give();
	return(true);
}

uint16_t uart::Read(uint8_t *ucData)
{
	uint16_t ret = mRecLen;
	
	if(mSource->SR_f.FE)
	{
		mSource->CR1_f.CFE = 1;
	}
	if(mSource->SR_f.PE)
	{
		mSource->CR1_f.CPE = 1;
	}
	if(mSource->SR_f.ORE)
	{
		mSource->CR1_f.CORE = 1;
	}
	if(!ret)
	{
		return(0);
	}
	memcpy(ucData, mRecBuff, ret);
	mRecLen = 0;
	mUartCreated[mUartInstance].usLenBack = 0;
	if(mDmaRecHandle)
	{
		dma::Reset(mDmaRecHandle, mUartCreated[mUartInstance].usBuffLimit, mUartCreated[mUartInstance].usBuffLimit, 0);
	}
	return(ret);
}

bool uart::Write(uint8_t *ucCmd, uint16_t usCmdLen, uint8_t *ucData, uint16_t usDataLen)
{
	return(false);
}

bool uart::Read(uint8_t *ucCmd, uint16_t usCmdLen, uint8_t *ucData, uint16_t usDataLen)
{
	return(false);
}

void uart::ParamSet(UartParityTPDF tParity, uint32_t uiBaudRate)
{
	BaudRate = uiBaudRate;
	Parity = tParity;
	Close();
	Open();
}
